其他
原来VSCode里藏了腾讯文档400行代码?鹅厂源码公开
👉腾小云导读
Visual Studio Code「VSCode」是 Microsoft 在2015年推出的、针对于编写现代 Web 和云应用的跨平台源代码编辑器,受到广大开发者热捧。腾讯文档向 VSCode 贡献了一些核心代码,主要涉及到 VSCode 配置化的部分,为其显著增强了配置化和插件化能力。作者希望将其中积累的经验分享出来,贡献给开源社区,为广大开发爱好者提供参考。本文详细解读源代码。欢迎阅读!👉看目录点收藏,随时涨技术
1 项目背景2 腾讯文档贡献源码分析3 腾讯文档给 VSCode 带来了什么4 总结01
腾讯文档在完善自己的配置化系统,在完善的过程探索了多种实现方案,分析了很多产品如大名鼎鼎的 VSCode 的实现方式。近期腾讯文档向 VSCode 贡献了 400 多行核心代码,主要涉及到 VSCode 配置化的部分。这增强了其插件化能力,提供更多的匹配接口。腾讯文档团队整理了部分代码结构和补充功能单测,希望把将这些积累的经验贡献给开源社区,与广大开发爱好者共同进步。公众后回复「VSCode」获取源代码。
02
"colors": {
"activityBar.background": "#333842",
"activityBar.foreground": "#D7DAE0",
"activityBarBadge.background": "#528BFF"
}
}
if (color) {
collector.addRule(
`.monaco-workbench .activitybar > .content > .home-bar > .home-bar-icon-badge { background-color: ${color}}`
);
}
if (isMacintosh) {
color = darken(color);
}
if (isWindows) {
color = lighter(color);
}
collector.addRule(
`.monaco-workbench .activitybar > .content > .home-bar > .home-bar-icon-badge { background-color: ${color}}`
);
}
if (isMacintosh || window.innerWidth > 855) {
color = darken(color);
}
if (isLinux) {
color = darken(color);
}
if (isWindows || window.innerWidth <= 855) {
color = lighter(color);
}
collector.addRule(
`.monaco-workbench .activitybar > .content > .home-bar > .home-bar-icon-badge { background-color: ${color}}`
);
}
color = theme.getColor(registerColor("activityBar.background"));
@If(isLinux)
@If(isMacintosh || window.innerWidth > 855)
darken() {
return darken(this.color);
}
@If(userRule1)
@If(userRule2)
@If(userRule3)
@If([isWindows, window.innerWidth <= 855].includes(true))
lighter() {
return lighter(this.color);
}
}
console.log(condition);
return (target: any, name?: any, descriptor?: any) => {
const func = descriptor?.value;
if (typeof func === "function") {
descriptor.value = function (...args: any) {
return condition && func.apply(this, args);
};
}
};
};
isLinux: JSON.stringify(true),
VERSION: JSON.stringify("5fa3b9"),
BROWSER_SUPPORTS_HTML5: true,
TWO: "1+1",
"typeof window": JSON.stringify("object"),
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
});
// if(isWindows || window.innerWidth <= 855) ...
// ↓
{
"darken": { "when": "isMacintosh || window.innerWidth > 855" },
"lighter": { "when": "isWindows || window.innerWidth <= 855" }
}
darken() {
return darken(this.color);
}
@If(JSON.lighter)
lighter() {
return lighter(this.color);
}
darken() {
return darken(this.color);
}
@If("isWindows || window.innerWidth <= 855")
lighter() {
return lighter(this.color);
}
"isWindows" => isWindows "isMacintosh || window.innerWidth > 855" => true/false |
"isMacintosh |&&| window.innerWidth > 855" => 非法配置参数 "isMacintosh \\// window.innerWidth > 855" => 非法配置参数 |
"lighter": { "when": "isWindows || window.innerWidth <= 855" }
}
context.set("isEdge", _userAgent.indexOf("Edg/") >= 0);
context.set("isFirefox", _userAgent.indexOf("Firefox") >= 0);
context.set("isChrome", _userAgent.indexOf("Chrome") >= 0);
context.set("isSafari", _userAgent.indexOf("Safari") >= 0);
context.set("isIPad", _userAgent.indexOf("iPad") >= 0);
context.set(window.innerWidth, () => window.innerWidth);
contextMatchesRules(context, ["isMacintosh"]); // true
contextMatchesRules(context, ["isEdge"]); // false
contextMatchesRules(context, ["window.innerWidth", ">=", "800"]); // true
03
支持变量
支持常量:布尔值、数字、字符串
支持正则
支持全等 in 和 typeof
支持全等 =、不等 !
支持与 &&、或 ||
支持大于 >、小于 <、大于等于 >=、小于等于 <=的比较运算
支持非!等逻辑运算
serialized: string,
strict: boolean
) => {
// 先解 ||
let pieces = serialized.split("||");
// 再解 &&
return ContextKeyOrExpr.create(pieces.map((p) => _deserializeAndExpression(p, strict)));
};
const _deserializeAndExpression: ContextKeyExpression | undefinedn = (
serialized: string,
strict: boolean
) => {
let pieces = serialized.split("&&");
return ContextKeyAndExpr.create(pieces.map((p) => _deserializeOne(p, strict)));
};
serializedOne: string,
strict: boolean
) => {
serializedOne = serializedOne.trim();
if (serializedOne.indexOf("!=") >= 0) {
let pieces = serializedOne.split("!=");
return ContextKeyNotEqualsExpr.create(
pieces[0].trim(),
this._deserializeValue(pieces[1], strict)
);
}
if (serializedOne.indexOf("==") >= 0) {
let pieces = serializedOne.split("==");
return ContextKeyEqualsExpr.create(
pieces[0].trim(),
this._deserializeValue(pieces[1], strict)
);
}
if (serializedOne.indexOf("=~") >= 0) {
let pieces = serializedOne.split("=~");
return ContextKeyRegexExpr.create(
pieces[0].trim(),
this._deserializeRegexValue(pieces[1], strict)
);
}
if (serializedOne.indexOf(" in ") >= 0) {
let pieces = serializedOne.split(" in ");
return ContextKeyInExpr.create(pieces[0].trim(), pieces[1].trim());
}
if (serializedOne.indexOf(">=") >= 0) {
const pieces = serializedOne.split(">=");
return ContextKeyGreaterEqualsExpr.create(pieces[0].trim(), pieces[1].trim());
}
if (serializedOne.indexOf(">") >= 0) {
const pieces = serializedOne.split(">");
return ContextKeyGreaterExpr.create(pieces[0].trim(), pieces[1].trim());
}
if (serializedOne.indexOf("<=") >= 0) {
const pieces = serializedOne.split("<=");
return ContextKeySmallerEqualsExpr.create(pieces[0].trim(), pieces[1].trim());
}
if (serializedOne.indexOf("<") >= 0) {
const pieces = serializedOne.split("<");
return ContextKeySmallerExpr.create(pieces[0].trim(), pieces[1].trim());
}
if (/^\!\s*/.test(serializedOne)) {
return ContextKeyNotExpr.create(serializedOne.substr(1).trim());
}
return ContextKeyDefinedExpr.create(serializedOne);
};
private readonly _defaultValue: T | undefined;
constructor(key: string, defaultValue: T | undefined) {
super(key);
this._defaultValue = defaultValue;
}
public toNegated(): ContextKeyExpression {
return ContextKeyExpr.not(this.key);
}
public isEqualTo(value: string): ContextKeyExpression {
return ContextKeyExpr.equals(this.key, value);
}
public notEqualsTo(value: string): ContextKeyExpression {
return ContextKeyExpr.notEquals(this.key, value);
}
}
const Extension = new RawContextKey<string>('resourceExtname', undefined);
Extension.isEqualTo("abc");
const ExtensionContext = new Maps();
ExtensionContext.setValue("resourceExtname", "abc");
console.log(contextMatchesRules(ExtensionContext, Extension.isEqualTo("abc")));
ContextKeyOrExpr: {
expr: [{
ContextKeyDefinedExpr: {
key: "canEdit",
type: 2
}
}, {
ContextKeyAndExpr: {
expr: [{
ContextKeyEqualsExpr: {
key: "platform",
type: 4,
value: "pc",
},
ContextKeyGreaterOrEqualsExpr: {
key: "window.innerWidth",
type: 12,
value: "1080",
}
}],
type: 6
}
}],
type: 9
}
}
protected readonly _values = new Map<string, any>();
public get values() {
return this._values;
}
public getValue(key: string): any {
if (this._values.has(key)) {
let value = this._values.get(key);
// 执行获取最新的值,并返回
if (typeof value == "function") {
value = value();
}
return value;
}
}
public removeValue(key: string): boolean {
if (key in this._values) {
this._values.delete(key);
return true;
}
return false;
}
public setValue(key: string, value: any) {
this._values.set(key, value);
}
}
context.setValue("platform", "pc");
context.setValue("window.innerWidth", () => window.innerWidth);
context.setValue(
"canEdit",
window.SpreadsheetApp.sheetStatus.rangesStatus.status.canEdit
);
context.setValue(JSON.stringify(false), false);
04
-End-
原创作者|姚嘉隆
技术责编|姚嘉隆
最近微信改版啦,有粉丝反馈收不到小云的文章🥹。
请关注「腾讯云开发者」并点亮星标,
周一三晚8点 和小云一起涨(领)技(福)术(利)!
你如何理解开源精神?怎么看待当下的开源现状?
如果只能给其他开发者推荐一个开源项目,你会推荐什么?
欢迎在评论区聊一聊你的看法。快来加腾小云的微信(微信号yun_assistant,统一处理时间9:00-18:00),在3月17日前将你的评论记录截图发送给小云,可领取腾讯云「开发者春季限定红包封面」一个,数量有限先到先得😄。我们还将选取点赞量最高的1位朋友,送出腾讯QQ公仔1个。3月22日中午12点开奖。快邀请你的开发者朋友们一起来参与吧!